﻿using System;
using System.Threading;
using Mbs.Messaging;
using NUnit.Framework;

namespace MBTest
{
    [TestFixture]
    public class MessageRouterTest
    {
        [Test]
        public void SimpleTest()
        {
            var mre = new ManualResetEvent(false);
            MB.Subscribe<int>((s,msg) =>
            {
                if (msg == -1)
                {
                    MB.Remove<int>();
                    mre.Set();
                }
                Console.WriteLine(msg.ToString());
            });

            for (int i = 0; i < 100; i++)
            {
                MB.Publish(i);
            }

            MB.Publish(-1);
            mre.WaitOne();
        }

        [Test]
        public void TopicTest()
        {
            const string topic = "TopicTest";
            var mre = new ManualResetEvent(false);

            MB.Subscribe<int>(topic,(s,msg )=>
            {
                if (msg.Message == -1)
                {
                    MB.Remove<int>(topic);
                    mre.Set();
                }
                Console.WriteLine(msg.ToString() + " for " + topic + "!");
                
            });

            for (int i = 0; i < 100; i++)
            {
                MB.Publish(topic, i);
            }

            MB.Publish(topic, -1);
            mre.WaitOne();

        }

        [Test]
        public void PreFilterTest()
        {
            const string topic = "PreFilterTest";
            var mre = new ManualResetEvent(false);

            MB.Subscribe<int>(topic, (s,msg) =>
            {
                //Assert.IsTrue(msg % 2 == 0);
                Console.WriteLine(msg.ToString() + " for " + topic + "!");
            });

            MB.SubscribePreFilter<int>(topic,(s, p) =>
            {
                p.Canceled = p.Message.Message % 2 != 0;
                if (p.Message.Message == -1)
                {
                    MB.Remove<int>(topic);

                    mre.Set();
                }
            });
            for (int i = 0; i < 100; i++)
            {
                MB.Publish(topic, i);
            }

            MB.Publish(topic, -1);
            mre.WaitOne();
        }

        [Test]
        public void FilterTest()
        {
            const string topic = "FilterTest";
            var mre = new ManualResetEvent(false);

            var noRunSubscriber = new FilterObject(topic);
            var subscriber = new NoFilterObject(topic);
            var subscriber2 = new NoFilterObject2(topic);
            var subscriber3 = new NoFilterObject3(topic);
            var subscriber4 = new NoFilterObject4(topic);
            var subscriber5 = new NoFilterObject5(topic);

            MB.SubscribePreFilter<int>(topic,(s, p) =>
            {
                
                if(p.Canceled = p.Message.Message == -1)
                    mre.Set();
            });

            MB.SubscribeFilter<int>(topic, (s,p) =>
            {
                p.Ignored = p.Receiver == null
                    || (p.Receiver != null && p.Receiver is IFilterObject);
            });

            for (int i = 0; i < 100; i++)
            {
                MB.Publish(topic, i);
            }


            MB.Publish(topic, -1);
            mre.WaitOne();
        }


        class FilterObject : IFilterObject
        {
            public FilterObject(string topic)
            {
                MB.Subscribe<int>(topic, (s, msg) =>
                {
                    Console.WriteLine("No executed in FilterObject");
                });
            }
        }

        interface IFilterObject
        {
        }
        class NoFilterObject
        {
            private string topic;
            private void Act(object sender,Topic<int> msg)
            {
                if (msg.Message % 2 != 0)
                    Console.WriteLine("NoFilterObject: " + msg.ToString() + " for " + topic + "!");
            }

            public NoFilterObject(string topic)
            {
                this.topic = topic;

                MB.Subscribe<int>(topic, Act);
            }
        }

        class NoFilterObject2
        {
            private string topic;
            private void Act(object sender, Topic<int> msg)
            {
                if (msg.Message % 2 == 0)
                    Console.WriteLine("NoFilterObject2: " + msg.ToString() + " for " + topic + "!");
            }

            public NoFilterObject2(string topic)
            {
                this.topic = topic;
                MB.Subscribe<int>(topic, Act);
            }
        }

        class NoFilterObject3
        {
            private string topic;

            public NoFilterObject3(string topic)
            {
                this.topic = topic;
                MB.Subscribe<int>(topic,(s, msg) => Console.WriteLine("No executed in NoFilterObject3!"));
            }
        }

        class NoFilterObject4
        {
            private string topic;

            public NoFilterObject4(string topic)
            {
                this.topic = topic;
                ObserverHandler<Topic<int>> act = (s,msg) =>
                {
                    Console.WriteLine("No executed in NoFilterObject4!");
                };

                MB.Subscribe<int>(topic, act);
            }
        }

        class NoFilterObject5
        {
            private string topic;

            public NoFilterObject5(string topic)
            {
                this.topic = topic;
                MB.Subscribe<int>(topic,NoFilterObject5_Receive);
            }

            void NoFilterObject5_Receive(object sender, Topic<int> msg)
            {
                if (msg.Message % 5 == 0)
                    Console.WriteLine("NoFilterObject5: " + msg.Message.ToString() + " for " + topic + "!");
            }
        }

        public static IMessageBus MB { get; protected set; }
        [SetUp]
        public virtual void Setup()
        {
            MB = new MessageBus(new Mbs.Messaging.Imp.PoolMessageRepository());
        }

        [TearDown]
        public void TearDown()
        {
            MB.Dispose();
        }
    }
  }
